import java.io.*;
import java.util.ArrayList;

/** @author Chris Howson & Steve Horsman */
public class MatrixCalc
//Got getters and setters, might need looking at steve
{
	ArrayList<InteractiveType> objlist = new ArrayList<InteractiveType>();
	
	public static void main(String[] args) throws FileNotFoundException
	{
		MatrixCalc program = new MatrixCalc();
		Matrix a = new MatrixArray();
		
		//BufferedReader standard = new BufferedReader(new FileReader("./test_files/matrixcalc.txt"));
		
		BufferedReader standard = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Input: Must contain spaces between commands and one operator at a time");
        try
        {
        	String inline = "";
            System.out.print(">>");
            inline = standard.readLine();
            inline.toLowerCase();
            System.out.print(inline + "\n");
            while(!inline.equals("exit"))
            {
            	String[] splitted = inline.split(" ");
            	if(splitted.length==4 && splitted[1].equals("="))
            	{
            		if(splitted[2].equals("load"))
            		{
	            		int pos = program.findmatrix(splitted[0]);
	            		System.out.println("Loading.." + splitted[3]);
	            		a = a.load_Matrix(splitted[3]);
	            		if(pos == -1)
	            		{
	            			program.objlist.add(new InteractiveType(splitted[0],a));
	            			System.out.println("Added " + splitted[0]);
	            		}
	            		else
	            		{
	            			program.objlist.get(pos).objmatrix = a;
	            		}
            		}
            		else if(splitted[2].equals("transpose"))
                	{
                		int pos = program.findmatrix(splitted[3]);
                		int anspos = program.findmatrix(splitted[0]);
            			if(pos==-1) { throw new Exception("Cannot Find Variable"); }
            			if(anspos==-1)
            			{
           					program.objlist.add(new InteractiveType(splitted[0],program.objlist.get(pos).objmatrix.transpose()));
            			}
            			else
            			{
           					program.objlist.get(pos).objmatrix= program.objlist.get(pos).objmatrix.transpose();
            			}
                	}
            		else if(splitted[2].equals("inverse"))
            		{
            			int anspos = program.findmatrix(splitted[0]);
            			int onepos = program.findmatrix(splitted[3]);
            			if(onepos==-1) { throw new Exception("Cannot Find Variabe"); }
            			if(anspos==-1)
            			{
            				program.objlist.add(new InteractiveType(splitted[0],program.objlist.get(onepos).objmatrix.inverse()));
            			}
            			else
            			{
            				program.objlist.get(anspos).objmatrix = program.objlist.get(onepos).objmatrix.inverse();
            			}
            		}
            	}
            	else if(splitted.length==2)
           		{
            		if(splitted[0].equals("print"))
            		{
            			int pos = program.findmatrix(splitted[1]);
            			if(pos == -1) { System.err.println("Cannot Find variable " + splitted[1]); }
            			else { program.objlist.get(pos).objmatrix.print(); }
            		}
            		else if(splitted[0].equals("determinant"))
            		{
            			int pos = program.findmatrix(splitted[1]);
            			if(pos==-1) { throw new Exception("Cannot Find Variable"); }
            			double apos = program.objlist.get(pos).objmatrix.determinant();
            			System.out.println("Determinant of Matrix " + splitted[1] + " = " + apos);
            		}
            	}
            	else if(splitted.length==3)
            	{
            		if(splitted[1].equals("="))
            		{
            			int pos = program.findmatrix(splitted[2]);
            			if(pos==-1) { throw new Exception("Cannot Find Variable"); }
            			program.objlist.add(new InteractiveType(splitted[0],program.objlist.get(pos).objmatrix));
            			System.out.println("Assigned " + splitted[0]);
            		}
            		if(splitted[0].equals("compare"))
            		{
            			int onepos = program.findmatrix(splitted[1]);
            			int twopos = program.findmatrix(splitted[2]);
            			if(onepos==-1 || twopos==-1) { throw new Exception("Cannot Find Variables"); }
            			Boolean t = program.objlist.get(onepos).objmatrix.compare_matrices(program.objlist.get(twopos).objmatrix);
            			if(t) { System.out.println(splitted[1] + " & " + splitted[2] + " are identical!"); }
            			else { System.out.println(splitted[1] + " & " + splitted[2] + " are NOT identical!"); }
            		}
            	}
            	else if(splitted.length==5 && splitted[1].equals("="))
            	{
            		int anspos = program.findmatrix(splitted[0]);
            		int onepos = program.findmatrix(splitted[2]);
            		int twopos = program.findmatrix(splitted[4]);
            		
           			if(anspos==-1)
           			{
           				program.objlist.add(new InteractiveType(splitted[0]));
           				anspos = program.objlist.size()-1;
           			}
           			if(splitted[3].equals("+"))
           			{
           				if((onepos==-1 || twopos==-1))
                		{
                			throw new Exception("Cannot find given variables");
                		}
           				program.objlist.get(anspos).objmatrix = program.objlist.get(onepos).objmatrix.add_matrices(program.objlist.get(twopos).objmatrix);
           			}
           			else if(splitted[3].equals("-"))
           			{
           				if((onepos==-1 || twopos==-1))
                		{
                			throw new Exception("Cannot find given variables");
                		}
           				program.objlist.get(anspos).objmatrix = program.objlist.get(onepos).objmatrix.subtract_matrices(program.objlist.get(twopos).objmatrix);
           			}
           			else if(splitted[3].equals("*"))
           			{
           				if(splitted[4].charAt(0) >= '0' && splitted[4].charAt(0) <='9')
           				{
           					if((onepos==-1))
                    		{
                    			throw new Exception("Cannot find given variables");
                    		}
           					program.objlist.get(anspos).objmatrix = program.objlist.get(onepos).objmatrix.scalarmul(Double.parseDouble(splitted[4]));
           				}
           				else
           				{
           					program.objlist.get(anspos).objmatrix = program.objlist.get(onepos).objmatrix.multiply(program.objlist.get(twopos).objmatrix);
           				}
           			}
            	}
            	System.out.print(">>");
                inline = standard.readLine();
                inline.toLowerCase();
                System.out.print(inline + "\n");
            }
        }
        catch(Exception e)
        {
        	System.out.println("Error: " + e);
        }
	}
	
	public InteractiveType getObjElement(int pos)
	{
		return objlist.get(pos);
	}
	
	public String getName(int pos)
	{
		return objlist.get(pos).name;
	}
	
	public Matrix getMatrix(int pos)
	{
		return objlist.get(pos).objmatrix;
	}
	
	public int findmatrix(String var_name)
	{
		for(int i = 0; i < objlist.size(); i++)
		{
			if(getObjElement(i).name.equals(var_name))
			{
				return i;
			}
		}
		return -1;
	}

}
